home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / ncsat.cpt / Telnet2.5 final / tcpip / bkgr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  37.5 KB  |  1,558 lines

  1. /*
  2. *  Background procedures for rcp and ftp
  3. *             11/86          Tim Krauskopf
  4. *  National Center for Supercomputing Applications
  5. *
  6. ****************************************************************************
  7. *                                                                          *
  8. *      part of:                                                            *
  9. *      Network utilities for NCSA Telnet                                   *
  10. *      by Tim Krauskopf                                                    *
  11. *                                                                          *
  12. *      National Center for Supercomputing Applications                     *
  13. *      152 Computing Applications Building                                 *
  14. *      605 E. Springfield Ave.                                             *
  15. *      Champaign, IL  61820                                                *
  16. *                                                                          *
  17. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  18. *                                                                          *
  19. ****************************************************************************
  20. *
  21. */
  22. #include <stdio.h>
  23. #include <fcntl.h>
  24. #include <string.h>
  25.  
  26. #include <Memory.h>
  27. #include <CType.h>
  28. #include <Dialogs.h>
  29. #include <ToolUtils.h>    /* BYU - for GetIndString() */
  30.  
  31. #include "whatami.h"
  32. #include "hostform.h"
  33. #include "menu.h"
  34. #include "user.h"
  35. #include "tools.h"
  36. #include "util.h"
  37. #include "macutil.h"
  38. #include "macbinary.h"
  39. #include "binsubs.h"
  40. #include "configrec.h"
  41. #include "maclook.h"
  42.  
  43. #define HTELNET 23
  44. #define HRSHD 514
  45. #define HFTP 21
  46. #define BUFFERS 8000
  47. #define PATHLEN 256
  48. #define MSG_RESOURCE_ID 23227    /* BYU */
  49.  
  50. #ifdef PC
  51.  
  52. #define RCPSEGSIZE 1024
  53. #define EOLCHAR 10
  54.  
  55. #ifdef MSC
  56. #define O_RAW O_BINARY
  57. #endif
  58.  
  59. #else
  60.  
  61. #define MACBINARY
  62.  
  63. #ifdef MACBINARY
  64. int
  65.     MacBinary=0;
  66. MBFile
  67.     *MBopen(),
  68.     *mbfp=NULL;
  69. extern int
  70.     defaultv;                        /* Default Volume from Maclook/Menu */
  71. #endif
  72.  
  73. #define RCPSEGSIZE 512
  74. #define O_RAW O_RDONLY
  75. #define EOLCHAR 13
  76. #endif
  77.  
  78.  
  79. int32 atol(),lseek();
  80.  
  81. extern void ftpmess();
  82. char *firstname(),*nextname(),*nextfile;
  83.  
  84. static  int
  85.     ftpenable=0,                /* is file transfer enabled? */
  86.     rcpenable=0,                /* is rcp enabled? */
  87. /*    ftpdata=-1,                    /* port for ftp data connection */    /* BYU 2.4.16 */
  88. /*    fnum=-1,                    /* port number for incoming ftp */    /* BYU 2.4.16 */
  89.     rsnum=-1,                    /* port number for incoming rshell */
  90.     rserr=-1;                    /* port number for rshd() stderr */
  91.  
  92. #ifdef PC
  93. static unsigned char xs[BUFFERS+10],    /* buffer space for file transfer */
  94.         pathname[PATHLEN],            /* space to keep path names */
  95.         newfile[PATHLEN],            /* current file being received */
  96.         myuser[17],                    /* user name on my machine */
  97.         hisuser[17],                /* user name on his machine */
  98.         waitchar;                    /* character waiting for from net */
  99. #else
  100. static  unsigned char *xs=0L,    /* buffer space for file transfer */
  101.         *pathname=0L,            /* space to keep path names */
  102.         *newfile=0L,            /* current file being received */
  103.         myuser[17],                    /* user name on my machine */
  104.         hisuser[17],                /* user name on his machine */
  105.         waitchar;                    /* character waiting for from net */
  106. #endif PC
  107.  
  108. static int 
  109.     curstate = -1,            /* state machine for background processes */
  110.     retstate = 200,            /* to emulate a subroutine call */
  111.     ftpstate = 0,            /* state of the ftp data transfer */
  112.     isdir=0,                /* flag for rcp target pathname */
  113.     waitpos=0,                /* marker for gathering strings from net */
  114.     cnt=0,                    /* number of characters from last netread() */
  115.     fh=0,                    /* file handle when transfer file is open */
  116.     ftpfh=0,                /* file handle for ftp data */
  117.     rc=0,                    /* telnet flag */
  118.     xp=0,                    /* general pointer */
  119.     towrite=0,                /* file transfer pointer */
  120.     len=0;                    /* file transfer length */
  121.  
  122. static long int
  123.     filelen=0L;                /* length of current file for transfer */
  124.  
  125. short mainport[NPORTS];        /* BYU 2.4.16 - map FTP data port to main port */
  126. short dataport[NPORTS];        /* BYU 2.4.16 - map FTP main port to data port */
  127. short mainstate[NPORTS];    /* BYU 2.4.16 */
  128. short datastate[NPORTS];    /* BYU 2.4.16 */
  129. short retnstate[NPORTS];    /* BYU 2.4.16 */
  130. short fileport[NPORTS];        /* BYU 2.4.16 */
  131.  
  132. extern char * mungbuf;
  133. static char crfound=0;
  134.  
  135.  
  136. extern char Sptypes[];        /* BYU 2.4.16 - flags for port #'s */
  137.  
  138. #define PFTP 1
  139. #define PRCP 2
  140. #define PDATA 3
  141.  
  142. #ifdef PC
  143.  
  144. #define ga()  while (!netwrite(rsnum,"",1)) netsleep(0)
  145.  
  146. /************************************************************************/
  147. /*  unsetrshd
  148. *   remove the acceptance of rshd calls (rcp)
  149. */
  150. unsetrshd()
  151.     {
  152.     netclose(rsnum);
  153.     rsnum = -1;
  154.     rcpenable = 0;
  155. }
  156.  
  157. /************************************************************************/
  158.  
  159. setrshd()
  160. {
  161.     int i;
  162. /*
  163. *  set up to receive a rsh call connection 
  164. */
  165.     if (rsnum >= 0)
  166.         return(0);
  167.     curstate = 199;                    /* waiting for connection */
  168.     i = netsegsize(RCPSEGSIZE);
  169.     rsnum = netlisten(HRSHD,0);        /* BYU 2.4.15 */
  170.     netsegsize(i);
  171.     if (rsnum >= 0)
  172.         Sptypes[rsnum] = PRCP;
  173.  
  174.     rcpenable = 1;
  175. }
  176.  
  177.  
  178. /************************************************************************/
  179. /*  rshell
  180. *   take an incoming rshell request and service it.  Designed to handle
  181. *   rcp primarily.
  182. */
  183. rshd(code)
  184.     int code;
  185.     {
  186.     int i,j;
  187.  
  188.     if (!rcpenable)
  189.         return(0);
  190.  
  191.     switch (curstate) {
  192.         case 199:                    /* wait to get started */
  193.             if (code != CONOPEN)
  194.                 break;
  195.  
  196.             curstate = 0;
  197.             netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  198.  
  199.             break;
  200.             
  201. /*
  202. * in effect, this is a subroutine that captures network traffic while
  203. * waiting for a specific character to be received
  204. */
  205.         case 50:
  206.             while (0 < (cnt = netread(rsnum,&xs[waitpos],1))) {
  207.                 if (xs[waitpos] == waitchar) {
  208.                     curstate = retstate;
  209.                     netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  210.                     break;
  211.                 }
  212.                 else 
  213.                     waitpos += cnt;
  214.             }
  215.             netpush(rsnum);
  216.             break;
  217.  
  218.         case 51:                /* for recursion, passes straight through */
  219.             break;
  220.  
  221.         case 0:                    /* waiting for first string */
  222.             retstate = 1;
  223.             curstate = 50;
  224.             waitchar = 0;
  225.             waitpos = 0;
  226.             netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  227.             break;
  228.  
  229.         case 1:                    /* we have received stderr port number */
  230.             i = atoi(xs);        /* port number */
  231.             curstate = 51;
  232. #ifdef notneeded
  233. /*
  234. *  caution, netrespond calls netsleep()
  235. *  which will call this routine
  236. *  careful with the synchronicity!
  237. */
  238.             if (i)        /* zero means, don't bother */
  239.                 rserr = netrespond(i,rsnum,1);    /* respond to rsh */
  240.             else
  241. #else
  242.             if (i) {
  243.                 cnt = -1;        /* abort it all, we don't take rsh */
  244.                 break;
  245.             }
  246.             else
  247. #endif
  248.                 rserr = -1;
  249.  
  250.             retstate = 2; curstate = 50;
  251.             waitpos = 0; waitchar = 0;
  252.             break;
  253.  
  254.         case 2:                /* get user name, my machine */
  255.             strncpy(myuser,xs,16);
  256.  
  257.             retstate = 3; curstate = 50;
  258.             waitpos = 0; waitchar = 0;
  259.             break;
  260.  
  261.         case 3:             /* get user name, his machine */
  262.             strncpy(hisuser,xs,16);
  263. /*            ftransinfo(hisuser); */
  264.  
  265.             retstate = 4; curstate = 50;
  266.             waitchar = 0; waitpos = 0;
  267.  
  268.             break;
  269.  
  270.         case 4:
  271. /*            ftransinfo(xs);*/
  272. /*
  273. * ACK receipt of command line
  274. */
  275.             if (rserr >= 0)
  276.                 netwrite(rserr,&xp,1);        /* send null byte */
  277.             else {
  278.                 ga();            /* send NULL on main connection */
  279.             }
  280.  
  281.             if (!strncmp(xs,"rcp ",4)) {
  282. /*
  283. *  rcp will be using wildcards, target must be a directory
  284. */
  285.                 if (!strncmp(&xs[4],"-d -t",5)) {
  286.                     strncpy(pathname,&xs[10],PATHLEN);
  287.                     if (direxist(pathname)) {
  288. /*                        ftransinfo("no directory by that name ");*/
  289.                         netwrite(rsnum,"\001 No dir found ",16);
  290.                         netpush(rsnum);
  291.                         cnt = -1;
  292.                         break;
  293.                     }
  294.  
  295.                     isdir = 1;
  296.                     retstate = 20; curstate = 50;
  297.                     waitchar = '\012'; waitpos = 0;
  298.  
  299.                     ga();        /* ready for them to start */
  300.                     break;
  301.                 }
  302. /*
  303. * target could be a directory or a complete file spec
  304. */
  305.                 if (!strncmp(&xs[4],"-t",2)) {
  306.                     strncpy(pathname,&xs[7],PATHLEN);
  307.                     if (!direxist(pathname)) 
  308.                         isdir = 1;
  309.                     else
  310.                         isdir = 0;
  311.  
  312.                     retstate = 20 ; curstate = 50;
  313.                     waitchar = '\012'; waitpos = 0;
  314.  
  315.                     ga();            /* ready for rcp to start */
  316.                     break;
  317.                 }
  318. /*
  319. *  rcp is requesting me to transfer file(s) (or giving directory name)
  320. */
  321.                 if (!strncmp(&xs[4],"-f",2)) {
  322.                     strncpy(pathname,&xs[7],PATHLEN);
  323.  
  324. /*
  325. *  direxist returns whether the path spec refers to a directory, and if
  326. *  it does, prepares it as a prefix.  Therefore, if it is a dir, we append
  327. *  a '*' to it to wildcard all members of the directory.
  328. *  Firstname() takes a file spec (with wildcards) and returns a pointer
  329. *  to a prepared ACTUAL file name.  nextname() returns successive ACTUAL
  330. *  filenames based on firstname().
  331. */
  332.                     if (!direxist(pathname)) {
  333.                         i = strlen(pathname);
  334.                         pathname[i] = '*';        /* all members of directory*/
  335.                         pathname[++i] = '\0';
  336.                     }
  337.                     nextfile = firstname(pathname);
  338.  
  339.                     if (nextfile == NULL) {
  340. /*                        ftransinfo(" file or directory not found ");*/
  341.                         netwrite(rsnum,"\001 File not found ",18);
  342.                         netpush(rsnum);
  343.                         cnt = -1;
  344.                     }
  345.                     else {
  346.                         /* wait for other side to be ready */
  347.                         retstate = 30;    curstate = 50;
  348.                         waitchar = 0; waitpos = 0;
  349.                     }
  350.                     break;
  351.                 }
  352.             }
  353.  
  354.             break;
  355.  
  356.         case 20:
  357.             xs[waitpos] = '\0';        /* add terminator */
  358.  
  359. /*
  360. *  get working values from command line just received
  361. *  open file for receive
  362. */
  363.             if (xs[0] != 'C' || xs[5] != ' ') {
  364. /*                ftransinfo(" Cannot parse filename line "); */
  365.                 netwrite(rsnum,"\001 Problem with file name ",26);
  366.                 cnt = -1;
  367.                 break;
  368.             }
  369.  
  370.             filelen = atol(&xs[6]);
  371.  
  372.             for (i = 6; xs[i] != ' '; i++) 
  373.                 if (!xs[i]) {
  374. /*                    ftransinfo(" premature EOL ");*/
  375.                     netwrite(rsnum,"\001 Problem with file name ",26);
  376.                     cnt = -1;
  377.                     break;
  378.                 }
  379.  
  380.             strcpy(newfile,pathname);        /* path spec for file */
  381.  
  382.             if (isdir)                        /* add file name for wildcards */
  383.                 strcat(newfile,&xs[++i]);
  384.  
  385.             if (0 > (fh = creat(newfile,O_RAW))) {
  386.                 netwrite(rsnum,"\001 Cannot open file for write ",29);
  387.                 cnt = -1;
  388.                 break;
  389.             }
  390.             netputevent(USERCLASS,RCPBEGIN,-1);
  391.             ga();                            /* start sending the file to me */
  392.             xp = len = 0;
  393.             curstate = 21;                    /* receive file, fall through */
  394.             break;
  395.  
  396.         case 21:
  397.             do {
  398.             /* wait until xs is full before writing to disk */
  399.                 if (len <= 0) {
  400.                     if (xp) {
  401.                         write(fh,xs,xp);
  402.                         xp = 0;
  403.                     }
  404.                     if (filelen > (long)BUFFERS)
  405.                         len = BUFFERS;
  406.                     else
  407.                         len = (int)filelen;
  408.                 }
  409.  
  410.                 cnt = netread(rsnum,&xs[xp],len);
  411.  
  412.                 filelen -= (long)cnt;
  413.                 len -= cnt;
  414.                 xp += cnt;
  415.  
  416. /*                printf(" %ld %d %d %d ",filelen,len,xp,cnt);
  417.                 n_row(); n_puts(""); */
  418.  
  419.                 if (filelen <= 0L || cnt < 0) {
  420.                     write(fh,xs,xp);        /* write last block */
  421.                     close(fh);
  422.                     fh = 0;
  423.                     
  424.                     /* wait for NULL byte at end after closing file */
  425.                     curstate = 50;  retstate = 22;
  426.                     waitchar = 0;   waitpos = 0;
  427.                     break;
  428.                 }
  429.  
  430.             } while (cnt > 0);
  431.             break;
  432.  
  433.         case 22:
  434.             /* cause next sequence of bytes to be saved as next filename
  435.                 to transfer     */
  436.             ga();            /* tell other side, I am ready */
  437.             waitchar = '\012'; waitpos = 0;
  438.             curstate = 50; retstate = 20;
  439.             break;
  440.  
  441. /*
  442. *  transfer file(s) to the sun via rcp
  443. */
  444.         case 30:
  445.             if (0 > (fh = open(nextfile,O_RAW))) {
  446.                 netwrite(rsnum,"\001 File not found ",19);
  447. /*                ftransinfo("Cannot open file to transfer: ");
  448.                 ftransinfo(nextfile); */
  449.                 cnt = -1;
  450.                 break;
  451.             }
  452.             netputevent(USERCLASS,RCPBEGIN,-1);
  453.             filelen = lseek(fh,0L,(short)2);    /* how long is file? */
  454.             lseek(fh,0L,0);                /* back to beginning */
  455.  
  456.             for (i=0,j=-1; nextfile[i] ; i++)
  457.                 if (nextfile[i] == '\\')
  458.                     j = i;
  459.  
  460.             sprintf(xs,"C0755 %lu %s\012",filelen,&nextfile[j+1]);
  461.             netwrite(rsnum,xs,strlen(xs));    /* send info to other side */
  462.  
  463. /*            ftransinfo(xs);                     check it */
  464.  
  465.             retstate = 31; curstate = 50;
  466.             waitchar = 0;  waitpos = 0;
  467.  
  468.             towrite = xp = 0;
  469.             break;
  470.  
  471.         case 31:
  472. /*
  473. *   we are in the process of sending the file 
  474. */
  475.             netputuev(SCLASS,RCPACT,rsnum);        /* keep us alive */
  476.  
  477.             if (towrite <= xp) {
  478.                 towrite = read(fh,xs,BUFFERS);
  479.                 xp = 0;
  480.                 filelen -= (long)towrite;
  481.             }
  482.             i = netwrite(rsnum,&xs[xp],towrite-xp);
  483.             if (i > 0)
  484.                 xp += i;
  485.  
  486. /*            printf(" %d %d %d %ld\012",i,xp,towrite,filelen);
  487.             n_row();
  488. */
  489. /*
  490. *  done if:  the file is all read from disk and all sent
  491. *  or other side has ruined connection
  492. */
  493.             if ((filelen <= 0L && xp >= towrite) || netest(rsnum)) {
  494.                 close(fh);
  495.                 fh = 0;
  496.                 nextfile = nextname();        /* case of wildcards */
  497.                 ga(); 
  498.                 netputuev(SCLASS,RCPACT,rsnum);
  499.                 if (nextfile == NULL)
  500.                     retstate = 32;
  501.                 else
  502.                     retstate = 30;
  503.                 curstate = 50;
  504.                 waitchar = 0;    waitpos = 0;
  505.             }
  506.             break;
  507.         case 32:
  508.             cnt = -1;
  509.             break;
  510.         case 5:
  511.             break;
  512.         default:
  513.             break;
  514.  
  515.     }
  516.  
  517. /*
  518. *  after reading from connection, if the connection is closed,
  519. *  reset up shop.
  520. */
  521.     if (cnt < 0) {
  522.         if (fh > 0) {
  523.             close(fh);
  524.             fh = 0;
  525.         }
  526.         curstate = 5;
  527.         cnt = 0;
  528.         netclose(rsnum);
  529.         rsnum = -1;
  530.         netputevent(USERCLASS,RCPEND,-1);
  531.  
  532.         setrshd();                    /* reset for next transfer */
  533.     }
  534.  
  535.  
  536. }
  537.  
  538. #endif
  539.  
  540. /***********************************************************************/
  541. /***********************************************************************/
  542. /***********************************************************************/
  543. /************************************************************************/
  544. /*  ftp section
  545. *   This should be extracted from rcp so that it compiles cleanly
  546. */
  547.  
  548. #if 0    /* BYU - replaced by CRESP code below */
  549. #define CRESP(A)  netpush(fnum);netwrite(fnum, messs[(A)], strlen(messs[(A)]))
  550. #endif    /* BYU */
  551.  
  552. #define FASCII 0
  553. #define FIMAGE O_RAW
  554. #define FAMODE 0
  555. #define FIMODE 1
  556. #define FMMODE 2            /* Mac Binary, when ready */
  557.  
  558. static int rfstate,
  559.     portnum[NPORTS][8],            /* BYU 2.4.16 */
  560.     ftpfilemode=FASCII,            /* how to open ze file */
  561.     ftptmode=FAMODE;            /* how to transfer ze file on net */
  562.  
  563. /*static uint16 fdport;        /* BYU 2.4.16 - made local to rftpd() */
  564.  
  565. extern int                     /* BYU 2.4.16 */
  566.     EtherNet;                /* BYU 2.4.16 - Signify Drivers */
  567.  
  568. unsigned char messs[100];        /* BYU */
  569.  
  570. void CRESP(fnum,msg_number) int fnum,msg_number; {    /* BYU 2.4.16 */
  571.   GetIndString(messs,MSG_RESOURCE_ID,msg_number+1);    /* BYU */
  572.   netpush(fnum);                                    /* BYU */
  573.   netwrite(fnum, &messs[1], (int) messs[0]);        /* BYU 2.4.9 */
  574. }                                                    /* BYU */
  575.  
  576. void setftp
  577.   (
  578.     void
  579.   )
  580.     {
  581.     short fnum,i1;                            /* BYU 2.4.16 */
  582.  
  583. /*
  584. *  set up to receive a telnet connection for ftp commands
  585. */
  586.     rfstate = 0;
  587.     ftpstate = 0;
  588.  
  589. /* Listen for FTP if we're not listening already */        /* BYU 2.4.16 */
  590.  
  591.     for (i1 = 0; i1 < NPORTS; i1++)                                         /* BYU 2.4.16 */
  592.         if ((Sptypes[i1] == PFTP) && (netporttype(i1) == NOT_FROM_SLIP))    /* BYU 2.4.16 */
  593.             break;                                                            /* BYU 2.4.16 */
  594.  
  595.     if (i1 >= NPORTS) {                                /* BYU 2.4.16 - non-SLIP listen */
  596.         fnum = netlisten(HFTP,NOT_FROM_SLIP);        /* BYU 2.4.16 - MacTCP listen */
  597.         ftpenable = 1;                                /* BYU 2.4.16 */
  598.  
  599.         if (fnum >= 0) {                            /* BYU 2.4.16 - signal that events should be caught */
  600.             Sptypes[fnum] = PFTP;                    /* BYU 2.4.16 */
  601.             dataport[fnum] = -1;                    /* BYU 2.4.16 - no data needed yet */
  602.             mainstate[fnum] = 0;                    /* BYU 2.4.16 */
  603.             datastate[fnum] = 0;                    /* BYU 2.4.16*/
  604.             retnstate[fnum] = 200;                    /* BYU 2.4.16 */
  605.         }                                            /* BYU 2.4.16 */
  606.     }                                                /* BYU 2.4.16 */
  607.  
  608. /* Listen for SLIP FTP using NCSA driver if the above is a MacTCP listen */    /* BYU 2.4.16 */
  609.  
  610.     if (EtherNet == -99) {                                        /* BYU 2.4.16 - MacTCP? */
  611.  
  612.         for (i1 = 0; i1 < NPORTS; i1++)                                     /* BYU 2.4.16 */
  613.             if ((Sptypes[i1] == PFTP) && (netporttype(i1) == FROM_SLIP))    /* BYU 2.4.16 */
  614.                 break;                                                        /* BYU 2.4.16 */
  615.  
  616.         if (i1 >= NPORTS) {                            /* BYU 2.4.16 - non-SLIP listen */
  617.             fnum = netlisten(HFTP,FROM_SLIP);        /* BYU 2.4.16 - NCSA listen for SLIP */
  618.             if (fnum >= 0) {                        /* BYU 2.4.16 - signal that events should be caught */
  619.                 Sptypes[fnum] = PFTP;                /* BYU 2.4.16 */
  620.                 dataport[fnum] = -1;                /* BYU 2.4.16 - no data needed yet */
  621.                 mainstate[fnum] = 0;                /* BYU 2.4.16 */
  622.                 datastate[fnum] = 0;                /* BYU 2.4.16*/
  623.                 retnstate[fnum] = 200;                /* BYU 2.4.16 */
  624.             }                                        /* BYU 2.4.16 */
  625.         }                                            /* BYU 2.4.16 */
  626.     }                                                /* BYU 2.4.16 */
  627.  
  628.     strcpy(myuser,"unknown");    /* set unknown user name */
  629. }
  630.  
  631. void unsetftp
  632.   (
  633.     void
  634.   )
  635.     {
  636.     short i1;                            /* BYU 2.4.16 */
  637.  
  638.     rfstate = 0;
  639.     ftpstate = 0;
  640.     for (i1 = 0; i1 < NPORTS; i1++) {    /* BYU 2.4.16 */
  641.         if (Sptypes[i1] == PFTP) {        /* BYU 2.4.16 */
  642.             netclose(i1);                /* BYU 2.4.16 */
  643.             Sptypes[i1] = -1;            /* BYU 2.4.16 */
  644.             mainstate[i1] = 0;            /* BYU 2.4.16 */
  645.             datastate[i1] = 0;            /* BYU 2.4.16*/
  646.         }                                /* BYU 2.4.16 */
  647.     }                                    /* BYU 2.4.16 */
  648. /*    fnum = -1;                            /* BYU 2.4.16 */
  649.     ftpenable = 0;
  650. }
  651.  
  652. #if 0        /* BYU - Converted to STR# resource number 23227 */
  653. /***********************************************************************/
  654. /*
  655. *  resident ftp server -- enables initiation of ftp without a username
  656. *  and password, as long as this telnet is active at the same time
  657. *  Now checks for the need of passwords.
  658. */
  659.  
  660. static char *messs[] = {
  661. #ifdef PC
  662.                         "220 PC Resident FTP server, ready \015\012",
  663. #else
  664.                         "220 Macintosh Resident FTP server, ready \015\012",
  665. #endif
  666.                         "451 Error in processing list command \015\012",
  667.                         "221 Goodbye \015\012",                        /*2*/
  668.                         "200 This space intentionally left blank <   > \015\012",
  669.                         "150 Opening connection \015\012",
  670.                         "226 Transfer complete \015\012",            /*5*/
  671.                         "200 Type set to A, ASCII transfer mode \015\012",
  672.                         "200 Type set to I, binary transfer mode \015\012",
  673.                         "500 Command not understood \015\012",        /*8*/
  674.                         "200 Okay \015\012",
  675.                         "230 User logged in \015\012",
  676.                         "550 File not found \015\012",                /*11*/
  677.                         "501 Directory not present or syntax error\015\012",
  678.                         "250 Chdir okay\015\012",
  679.                         "257 \"",
  680.                         "\" is the current directory \015\012",        /*15*/
  681.                         "501 File not found \015\012",
  682.                         "504 Parameter not accepted, not implemented\015\012",
  683.                         "200 Stru F, file structure\015\012",
  684.                         "200 Mode S, stream mode\015\012",        /*19*/
  685.                         "202 Allocate and Account not required for this server\015\012",
  686.                         "501 Cannot open file to write, check for valid name\015\012",
  687.                         "530 USER and PASS required to activate me\015\012",
  688.                         "331 Password required\015\012",      /*23 */
  689.                         "530 Login failed\015\012",
  690.                         "200 MacBinary Mode enabled\015\012",
  691.                         "200 MacBinary Mode disabled\015\012",  /*26 */
  692.                         "552 Disk write error, probably disk full\015\012",
  693.                         "214-NCSA Telnet FTP server, supported commands:\015\012",
  694.                         "    USER  PORT  RETR  ALLO  PASS  STOR  CWD  XCWD  XPWD  LIST  NLST\015\012",
  695. #ifdef MAC
  696.                         "    HELP  QUIT  MODE  TYPE  STRU  ACCT  NOOP  MACB\015\012",  /*30*/
  697.                         "    MACB is MacBinary and must be done with TYPE I\015\012",
  698. #else
  699.                         "    HELP  QUIT  MODE  TYPE  STRU  ACCT  NOOP\015\012",
  700.                         "    A Macintosh version of NCSA Telnet is also available.\015\012",
  701. #endif
  702.                         "214 Direct comments and bugs to telbug@ncsa.uiuc.edu\015\012",
  703.                         "200 Type set to I, binary transfer mode [MACBINARY ENABLED]\015\012",                /* 33 */
  704.                         "200 Type set to I, binary transfer mode [macbinary disabled]\015\012",
  705.                 ""};
  706.  
  707. /***********************************************************************/
  708. #endif        /* BYU */
  709.  
  710. /* ftpgo
  711. *  open the FTP data connection to the remote host
  712. */
  713. int ftpgo                    /* BYU 2.4.16 MPW */
  714.   (
  715.     int fnum                /* BYU 2.4.16 */
  716.   )
  717.     {
  718.     int ftpdata,savest;        /* BYU 2.4.16 */
  719.     struct machinfo *m;
  720.  
  721.     xs[0] = portnum[fnum][0];    /* BYU 2.4.16 */
  722.     xs[1] = portnum[fnum][1];    /* BYU 2.4.16 */
  723.     xs[2] = portnum[fnum][2];    /* BYU 2.4.16 */
  724.     xs[3] = portnum[fnum][3];    /* BYU 2.4.16 */
  725.  
  726.     netfromport(20);     /* ftp data port */
  727.  
  728.     if (NULL == (m = Slookip(xs))) {        /* use default entry */
  729.         if (NULL == (m = Shostlook("default")))
  730.             return(-1);                                /* BYU 2.4.16 MPW */
  731.         savest = m->mstat;
  732.         m->mstat = HAVEIP;
  733.         movebytes(m->hostip,xs,4);
  734.         ftpdata = Snetopen(m,fileport[fnum],netporttype(fnum));        /* BYU 2.4.16 */
  735.         m->mstat = savest;
  736.         movebytes(m->hostip,"\0\0\0\0",4);
  737.         mainport[ftpdata] = fnum;                                    /* BYU 2.4.16 */
  738.         dataport[fnum] = ftpdata;                                    /* BYU 2.4.16 */
  739.         return(ftpdata);                                            /* BYU 2.4.16 */
  740.     }
  741.  
  742.     ftpdata = Snetopen(m,fileport[fnum],netporttype(fnum));            /* BYU 2.4.16 */
  743.     mainport[ftpdata] = fnum;                                        /* BYU 2.4.16 */
  744.     dataport[fnum] = ftpdata;                                        /* BYU 2.4.16 */
  745.     return(ftpdata);                                                /* BYU 2.4.16 */
  746.  
  747. }
  748.  
  749. void rftpd
  750.   (
  751.     int code,                                /* BYU 2.4.16 */
  752.     int fnum                                /* BYU 2.4.16 */
  753.   )
  754.     {
  755.     int fdport,ftpdata,i;                    /* BYU 2.4.16 */
  756.     char tempp[256];
  757.     char theDir[256];
  758.     if (!ftpenable)
  759.         return;
  760.  
  761.     netpush(fnum);
  762.  
  763.     rfstate = mainstate[fnum];                /* BYU 2.4.16 */
  764.     ftpstate = datastate[fnum];                /* BYU 2.4.16 */
  765.     retstate = retnstate[fnum];                /* BYU 2.4.16 */
  766.     fdport = fileport[fnum];                /* BYU 2.4.16 */
  767.  
  768.     switch (rfstate) {
  769.         case 0:
  770.             if (code != CONOPEN) 
  771.                 break;
  772.             ftpfilemode = FASCII;
  773.             ftptmode = FAMODE;
  774.             netputevent(USERCLASS,FTPCOPEN,-1);
  775. #ifndef PC
  776.             if (!xs) xs=(char *)NewPtr(BUFFERS+10);
  777.             if (!pathname) pathname=(char *)NewPtr(PATHLEN);
  778.             if (!newfile) newfile=(char *)NewPtr(PATHLEN);
  779. #endif PC
  780.             rfstate = 1;                /* drop through */
  781.         case 1:
  782.             CRESP(fnum,0);                            /* BYU 2.4.16 */
  783.             netgetftp(&portnum[fnum][0],fnum);        /* BYU 2.4.16 - get default ftp information */
  784.             for (i=0; i<4; i++)            /* copy IP number */
  785.                 hisuser[i] = portnum[fnum][i];                    /* BYU 2.4.16 */
  786.             fdport = portnum[fnum][6]*256+portnum[fnum][7];        /* BYU 2.4.16 */
  787.  
  788.             waitpos = 0; waitchar = '\012';
  789.             rfstate = 50;               /* note skips over */
  790.             if (Sneedpass()) 
  791.                 retstate = 3;                /* check pass */
  792.             else
  793.                 retstate = 5;                /* who needs one ? */
  794.             break;
  795.         case 3:                /* check for passwords */
  796.         case 4:
  797.             waitpos = 0;  waitchar = '\012';
  798.             rfstate = 50;  
  799.             if (!strncmp("USER",xs,4)) {
  800.                 if (strlen(xs) < 6)                /* make sure blank name stays blank */
  801.                     xs[5] = myuser[0] = 0;
  802.                 strncpy(myuser,&xs[5],16);        /* keep user name */
  803.                 netputevent(USERCLASS,FTPUSER,-1);
  804.                 CRESP(fnum,23);                                        /* BYU 2.4.16 */
  805.                 retstate = 4;        /* wait for password */
  806.                 break;
  807.             }
  808.             if (!strncmp("PASS",xs,4)) {
  809.                 if (Scheckpass(myuser,&xs[5])) {
  810.                     netputevent(USERCLASS,FTPPWOK,-1);
  811.                     CRESP(fnum,10);                                    /* BYU 2.4.16 */
  812.                     retstate = 5;
  813.                 }
  814.                 else {
  815.                     netputevent(USERCLASS,FTPPWNO,-1);
  816.                     CRESP(fnum,24);                                    /* BYU 2.4.16 */
  817.                     retstate = 3;
  818.                 }
  819.                 break;
  820.             }
  821.             if (!strncmp("QUIT",xs,4)) {
  822.                 CRESP(fnum,2);                        /* BYU 2.4.16 */
  823.                 cnt = -1;
  824.             }
  825.             else {
  826.                 CRESP(fnum,22);        /* BYU 2.4.16 */
  827.             }
  828.             retstate = 3;            /* must have password first */
  829.             break;                
  830.                 
  831. /*
  832. *  interpret commands that are received from the other side
  833. */
  834.             
  835.         case 5:
  836. #ifdef PC
  837.             for (i=4; i< strlen(xs); i++)
  838.                 if (xs[i] == '/')        /* flip slashes */
  839.                     xs[i] = '\\';
  840. #endif
  841.  
  842. /*
  843. *  set to a safe state to handle recursion
  844. *  wait for another command line from client
  845. *  
  846. */
  847.             rfstate = 50; retstate = 5;
  848.             waitchar = '\012';  waitpos = 0;
  849.  
  850.             if (!strncmp(xs,"LIST",4) || !strncmp(xs,"NLST",4)) {
  851.                 if ((strlen(xs) < 6) || xs[5] == '.')
  852.                     strcpy(xs,"LIST *");
  853.  
  854.                 nextfile = firstname(&xs[5]);    /* find first name */
  855.                 if (nextfile == NULL) {
  856.                     CRESP(fnum,16);                /* BYU 2.4.16 */
  857.                 }
  858.                 else {
  859.                     ftpdata = ftpgo(fnum);                /* BYU 2.4.16 - open the connection */
  860.                     fdport = portnum[fnum][6]*256+portnum[fnum][7]; /* BYU 2.4.16 - reset to def */
  861.  
  862.                     if (ftpdata >= 0)
  863.                         Sptypes[ftpdata] = PDATA;
  864.                     ftpstate = 40;        /* ready to transmit */
  865.                     CRESP(fnum,4);                            /* BYU 2.4.16 */
  866.                     netputevent(USERCLASS,FTPLIST,-1);
  867.                 }
  868.             }
  869.             else if (!strncmp(xs,"CWD",3)) {
  870.                 if (chgdir(&xs[4])) {            /* failed */
  871.                     CRESP(fnum,12);                /* BYU 2.4.16 */
  872.                 }
  873.                 else {                        /* success */
  874.                     CRESP(fnum,13);            /* BYU 2.4.16 */
  875.                 }
  876.             }
  877.             else if (!strncmp(xs,"STOR",4))
  878.               {
  879. #ifdef MACBINARY
  880.               /* had to simplify this, else MPW C 3.0/3.1 generates bad code! */
  881.                 int
  882.                     MBflag;
  883.                 if ((!MacBinary) || (ftptmode == FAMODE))
  884.                     MBflag = MB_DISABLE;
  885.                 else
  886.                     MBflag = 0;
  887.                 mbfp = MBopen
  888.                   (
  889.                     &xs[5],
  890.                     defaultv,
  891.                     MB_WRITE | MBflag
  892.                   );
  893.                 if (mbfp == 0L)
  894.                   {
  895.                     CRESP(fnum,21);            /* BYU 2.4.16 */
  896.                     break;
  897.                   }
  898.                 else
  899.                     ftpfh = 12;
  900. #else
  901.  
  902.                 if (0 > (ftpfh = creat(&xs[5],ftpfilemode))) {
  903.                     CRESP(fnum,21);            /* BYU 2.4.16 */
  904.                     break;
  905.                 }
  906. #endif
  907.  
  908.                 ftpstate = 0;
  909.  
  910.                 strncpy(newfile,&xs[5],PATHLEN-1);
  911.                 
  912.  
  913.                 ftpdata = ftpgo(fnum);                /* BYU 2.4.16 - open connection */
  914.                 fdport = portnum[fnum][6]*256+portnum[fnum][7]; /* BYU 2.4.16 - reset to def */
  915.  
  916.                 if (ftpdata >= 0)
  917.                     Sptypes[ftpdata] = PDATA;
  918.  
  919.                 CRESP(fnum,4);        /* BYU 2.4.16 */
  920.  
  921.                 ftpstate = 30;        /* ready for data */
  922.               }
  923.  
  924.             else if (!strncmp(xs,"RETR",4))
  925.               {
  926. #ifdef MACBINARY
  927.               /* had to simplify this, else MPW C 3.0/3.1 generates bad code! */
  928.                 int
  929.                     MBflag;
  930.                 if ((!MacBinary) || (ftptmode == FAMODE))
  931.                     MBflag = MB_DISABLE;
  932.                 else
  933.                     MBflag = 0;
  934.                 mbfp = MBopen
  935.                   (
  936.                     &xs[5],
  937.                     defaultv,
  938.                     MB_READ | MBflag
  939.                   );
  940.                 if (mbfp == 0L) {
  941.                     CRESP(fnum,11);                        /* BYU 2.4.16 */
  942.                     break;
  943.                 }
  944.                 ftpfh = 12;
  945. #else
  946.                 if (0 > (ftpfh = open(&xs[5],ftpfilemode))) {
  947.                     CRESP(fnum,11);                        /* BYU 2.4.16 */
  948.                     break;
  949.                 }
  950. #endif
  951.                 strncpy(newfile,&xs[5],PATHLEN-1);
  952.  
  953.                 dopwd(theDir,256);                    /* get directory */
  954.                 sprintf(tempp,"remote <-- %s/%s\015\012",theDir,newfile);
  955.                 ftpmess(tempp);
  956.  
  957.                 ftpdata = ftpgo(fnum);                /* BYU 2.4.16 - open connection */
  958.                 fdport = portnum[fnum][6]*256+portnum[fnum][7]; /* BYU 2.4.16 - reset to def */
  959.  
  960.                 ftpstate = 20;        /* ready for data */
  961.                 if (ftpdata >= 0)
  962.                     Sptypes[ftpdata] = PDATA;
  963.  
  964.                 CRESP(fnum,4);                            /* BYU 2.4.16 */
  965.               }
  966.             else if (!strncmp(xs,"TYPE",4)) {
  967.                 if (toupper(xs[5]) == 'I') {
  968.                     ftpfilemode = FIMAGE;
  969.                     ftptmode = FIMODE;
  970. #ifdef MACBINARY
  971.                 if (MacBinary) {
  972.                     CRESP(fnum,33);                    /* BYU 2.4.16 - Binary on, MACB ON */
  973.                 }
  974.                 else {
  975.                     CRESP(fnum,34);                    /* BYU 2.4.16 - Binary on, MACB off */
  976. #else
  977.                     CRESP(fnum,7);                    /* BYU 2.4.16 */
  978. #endif MACBINARY
  979.                 }
  980.                 }
  981.                 else if (toupper(xs[5]) == 'A') {
  982.                     ftpfilemode = FASCII;
  983.                     ftptmode = FAMODE;
  984.                     CRESP(fnum,6);                    /* BYU 2.4.16 */
  985.                 }
  986.                 else {
  987.                     CRESP(fnum,17);                    /* BYU 2.4.16 */
  988.                 }
  989.  
  990.             }
  991. #ifdef MACBINARY
  992.             else if (!strncmp(xs,"MACB",4)) {
  993.                 if (toupper(xs[5]) == 'E') {
  994.                     MacBinary = 1;
  995.                     CRESP(fnum,25);                    /* BYU 2.4.16 */
  996.                 }
  997.                 else {
  998.                     MacBinary = 0;
  999.                     CRESP(fnum,26);                    /* BYU 2.4.16 */
  1000.                 }
  1001.                 DisplayMacBinary();            /* post an event ? */
  1002.             }
  1003. #endif
  1004.             else if (!strncmp(xs,"PORT",4)) {
  1005. /*
  1006. * get the requested port number from the command given
  1007. */
  1008.                 sscanf((char *) &xs[5],"%d,%d,%d,%d,%d,%d",        /* BYU 2.4.16 */
  1009.                     &portnum[fnum][0],&portnum[fnum][1],        /* BYU 2.4.16 */
  1010.                     &portnum[fnum][2],&portnum[fnum][3],        /* BYU 2.4.16 */
  1011.                     &portnum[fnum][4],&portnum[fnum][5]);        /* BYU 2.4.16 */
  1012.                 fdport = portnum[fnum][4]*256+portnum[fnum][5];    /* BYU 2.4.16 */
  1013.                 CRESP(fnum,3);                            /* BYU 2.4.16 */
  1014.             }
  1015.             else if (!strncmp(xs,"QUIT",4)) {
  1016.                 CRESP(fnum,2);                            /* BYU 2.4.16 */
  1017.                 rfstate = 60;
  1018.                 netputuev(CONCLASS,CONDATA,fnum);    /* post back to me */
  1019.             }
  1020.             else if (!strncmp(xs,"XPWD",4) || !strncmp(xs,"PWD",3)) {
  1021.                 CRESP(fnum,14);                        /* BYU 2.4.16 - start reply */
  1022.                 dopwd(xs,1000);                    /* get directory */
  1023.                 netwrite(fnum,xs,strlen(xs));    /* write dir name */
  1024.                 CRESP(fnum,15);                        /* BYU 2.4.16 - finish reply */
  1025.             }
  1026.             else if (!strncmp(xs,"USER",4)) {
  1027.                 if (strlen(xs) < 6)                /* make sure blank name stays blank */
  1028.                     xs[5] = myuser[0] = 0;
  1029.                 strncpy(myuser,&xs[5],16);        /* keep user name */
  1030.                 netputevent(USERCLASS,FTPUSER,-1);
  1031.                 /* confirm log in without password */
  1032.                 CRESP(fnum,10);                            /* BYU 2.4.16 */
  1033.             }
  1034.             else if (!strncmp(xs,"STRU",4)) {    /* only one stru allowed */
  1035.                 if (xs[5] == 'F') {
  1036.                     CRESP(fnum,18); }                    /* BYU 2.4.16 */
  1037.                 else {
  1038.                     CRESP(fnum,17); }                    /* BYU 2.4.16 */
  1039.             }
  1040.             else if (!strncmp(xs,"MODE",4)) {    /* only one mode allowed */
  1041.                 if (xs[5] == 'S') {
  1042.                     CRESP(fnum,19); }                    /* BYU 2.4.16 */
  1043.                 else {
  1044.                     CRESP(fnum,17); }                    /* BYU 2.4.16 */
  1045.             }
  1046.             else if (!strncmp(xs,"ALLO",4) || !strncmp(xs,"ACCT",4)) {
  1047.                 CRESP(fnum,20); }                        /* BYU 2.4.16 */
  1048.             else if (!strncmp(xs,"HELP",4)) {
  1049.                 for (i=28; i<33; i++) {
  1050.                     CRESP(fnum,i); }                    /* BYU 2.4.16 */
  1051.             }
  1052.             else if (!strncmp(xs,"NOOP",4)) {
  1053.                 CRESP(fnum,9); }                            /* BYU 2.4.16 */
  1054.             else {            /* command not understood */
  1055.                 CRESP(fnum,8);                                 /* BYU 2.4.16 */
  1056.             }
  1057.  
  1058.             break;
  1059.  
  1060. /*
  1061. *  subroutine to wait for a particular character
  1062. */
  1063.         case 50:
  1064.             while (0 < (cnt = netread(fnum,&xs[waitpos],1))) {
  1065.                 if (xs[waitpos] == waitchar) {
  1066.                     rfstate = retstate;
  1067.  
  1068.                     while (xs[waitpos] < 33)        /* find end of string */
  1069.                         waitpos--;
  1070.                     xs[++waitpos] = '\0';            /* put in terminator */
  1071.  
  1072.                     for (i=0; i<4; i++)                /* want upper case */
  1073.                         xs[i] = toupper(xs[i]);
  1074.  
  1075.                     break;
  1076.                 }
  1077.                 else
  1078.                     waitpos += cnt;
  1079.  
  1080.             }
  1081.             break;
  1082.  
  1083.         case 60:                    /* wait for message to get through */
  1084.                                     /* or connection is broken */
  1085. /*            printf("                  %d,%d",netpush(fnum),netest(fnum));*/
  1086.             if (!netpush(fnum) || netest(fnum))
  1087.                 cnt = -1;
  1088.             else
  1089.                 netputuev(CONCLASS,CONDATA,fnum);    /* post back to me */
  1090.             break;
  1091.  
  1092.         default:
  1093.             break;
  1094.  
  1095.     }
  1096.  
  1097.     if (cnt < 0) {
  1098. #ifdef MACBINARY
  1099.         if (mbfp) {
  1100.             MBclose( mbfp );
  1101.             mbfp = NULL;
  1102.         }
  1103. #else
  1104.         if (ftpfh > 0) {
  1105.             ftpfh = 0;
  1106.             close(ftpfh);
  1107.         }
  1108. #endif
  1109.         ftpdata = dataport[fnum];                    /* BYU 2.4.16 */
  1110.         if (ftpdata > 0) {
  1111.             netclose(ftpdata);
  1112.             netputevent(USERCLASS,FTPEND,-1);
  1113.             dataport[fnum] = -1;                    /* BYU 2.4.16 */
  1114.             mainport[ftpdata] = -1;                    /* BYU 2.4.16 */
  1115.         }
  1116.         rfstate = 100;
  1117.         ftpstate = 0;
  1118.         cnt = 0;
  1119.         netclose(fnum);
  1120.         Sptypes[fnum] = -1;                            /* BYU 2.4.16 */
  1121.         netputevent(USERCLASS,FTPCLOSE,-1);
  1122. #if 0                                                /* BYU 2.4.16 */
  1123.         fnum = -1;
  1124.         ftpdata = -1;
  1125. #endif                                                /* BYU 2.4.16 */
  1126.         setftp();                /* reset it */
  1127.     }
  1128.  
  1129.     mainstate[fnum] = rfstate;                        /* BYU 2.4.16 */
  1130.     datastate[fnum] = ftpstate;                        /* BYU 2.4.16 */
  1131.     retnstate[fnum] = retstate;                        /* BYU 2.4.16 */
  1132.     fileport[fnum] = fdport;                        /* BYU 2.4.16 */
  1133.  
  1134. }
  1135.  
  1136. /*
  1137. *  important note:  for Sfread, nwant must be 256 bytes LARGER than the amount
  1138. *  which will probably be read from the connection.
  1139. *  Sfread will stop anywhere from 0 to 256 bytes short of filling nwant
  1140. *  number of bytes.
  1141. */
  1142. int Sfread
  1143.   (
  1144.     int pnum,
  1145.     void *buf,
  1146.     int nwant
  1147.   )
  1148.     {
  1149.     int i,ndone,lim;
  1150.     char *p,*q;
  1151.  
  1152.     if (nwant < 1024)
  1153.         return(-1);
  1154.  
  1155.     ndone = 0;
  1156.  
  1157.     while (ndone < nwant - 1024) {
  1158.  
  1159.         if (0 >= (lim = netread(pnum,mungbuf,1024))) {
  1160.             if (ndone || !lim)            /* if this read is valid, but no data */
  1161.                 return(ndone);
  1162.             else
  1163.                 return(-1);                /* if connection is closed for good */
  1164.         }
  1165.  
  1166.         p = mungbuf;
  1167.         q = (char *) buf + ndone;
  1168.  
  1169. /*        printf("\012 lim=%d done=%d want=%d",lim,ndone,nwant);
  1170.         n_row();
  1171. */
  1172.         for (i=0; i < lim; i++) {
  1173.  
  1174.             if (crfound) {
  1175.                 if (*p == 10)
  1176.                     *q++ = EOLCHAR;
  1177.                 else if (*p == 0)
  1178.                     *q++ = 13;            /* CR-NUL means CR */
  1179.                 crfound = 0;
  1180.             }
  1181.             else if (*p == 13)
  1182.                 crfound = 1;
  1183.             else 
  1184.                 *q++ = *p;                /* copy the char */
  1185.  
  1186.             p++;
  1187.         }
  1188.  
  1189.         ndone = q-buf;                    /* count chars ready */
  1190.     }
  1191.  
  1192.     return(ndone);
  1193. }
  1194.  
  1195. /***************************************************************************/
  1196. /*  Sfwrite
  1197. *   Write an EOL translated buffer into netwrite.
  1198. *   Returns the number of bytes which were processed from the incoming
  1199. *   buffer.  Uses its own 1024 byte buffer for the translation (with Sfread).
  1200. */
  1201.  
  1202. int Sfwrite
  1203.   (
  1204.     int pnum,
  1205.     void *buf,
  1206.     int nsrc
  1207.   )
  1208.     {
  1209.     int i,ndone,nout,lim;
  1210.     char *p,*q;
  1211.  
  1212.     ndone = 0;
  1213.  
  1214.     while (ndone < nsrc) {
  1215.  
  1216.         if (0 > ( i = netroom(pnum)))
  1217.             return(-1);
  1218.  
  1219.         if (i < 1024)                    /* not enough room to work with */
  1220.             return(ndone);
  1221. /*
  1222. *  process up to 512 source bytes for output (could produce 1K bytes out) 
  1223. */
  1224.         if (nsrc - ndone > 512)
  1225.             lim = 512;
  1226.         else
  1227.             lim = nsrc-ndone;
  1228.  
  1229.         p = (char *) buf + ndone;                /* where to start this block */
  1230.         q = mungbuf;                    /* where munged stuff goes */
  1231.         for (i=0; i < lim; i++) {
  1232.             if (*p == EOLCHAR) {
  1233.                 *q++ = 13;
  1234.                 *q++ = 10;
  1235.                 p++;
  1236.             }
  1237.             else
  1238.                 *q++ = *p++;
  1239.         }
  1240.         ndone += lim;                    /* # of chars processed */
  1241.         nout = q-mungbuf;                /* # of chars new */
  1242.  
  1243.         if ( nout != netwrite(pnum,mungbuf,nout) )
  1244.             putln("error in Sfwrite");    /* send them on their way */
  1245.  
  1246.     }
  1247.  
  1248.     return(ndone);
  1249. }
  1250.  
  1251. /*********************************************************************/
  1252. /*
  1253. *  FTP receive and send file functions
  1254. */
  1255. static int fcnt=0;
  1256.  
  1257. void ftpd
  1258.   (
  1259.     int code,
  1260.     int ftpdata                            /* BYU 2.4.16 */
  1261.   )
  1262.     {
  1263.     short fnum = mainport[ftpdata];        /* BYU 2.4.16 */
  1264.     int i,a;
  1265.     char tempp[256];
  1266.     char theDir[256];
  1267.  
  1268. /*    if (curcon != ftpdata)                /* BYU 2.4.16 - wrong event, was for someone else */
  1269. /*        return;                            /* BYU 2.4.16 */
  1270.  
  1271.     ftpstate = datastate[fnum];            /* BYU 2.4.16 */
  1272.  
  1273.     switch (ftpstate) {
  1274.         default:
  1275.             break;
  1276.  
  1277.         case 40:                /* list file names in current dir */
  1278.  
  1279.             if (code == CONFAIL)    /* something went wrong */
  1280.                 fcnt = -1;
  1281.             if (code != CONOPEN)     /* waiting for connection to open */
  1282.                 break;
  1283.             
  1284.             ftpstate = 41;
  1285.  
  1286. /*
  1287. *  send the "nextfile" string and then see if there is another file
  1288. *  name to send
  1289. */
  1290.         case 41:
  1291.             netputuev(SCLASS,FTPACT,ftpdata);
  1292.             netpush(ftpdata);
  1293.             strncat (nextfile,"\015\012",2);
  1294.             i = strlen(nextfile);
  1295.             if (i != netwrite(ftpdata,nextfile,i)) {
  1296.                 CRESP(fnum,1);                        /* BYU 2.4.16 */
  1297.                 fcnt = -1;
  1298.                 break;
  1299.             }
  1300.  
  1301. /*            netwrite(ftpdata,"\015\012",2);     Lets not do that!!! */
  1302. /*            netwrite CRLF causes problems on some systems (thanx, Jim!) */
  1303.  
  1304.             if (NULL == (nextfile = nextname())) {    /* normal end */
  1305.                 ftpstate = 22;               /* push data through */
  1306.             }
  1307.             break;
  1308.             
  1309.         case 30:
  1310.             if (code == CONFAIL)    /* something went wrong */
  1311.                 fcnt = -1;
  1312.             if (code != CONOPEN)    /* waiting for connection to open */
  1313.                 break;
  1314.             ftpstate = 31;
  1315.             crfound = 0;
  1316.             len = xp = 0;
  1317.             filelen = 0L;
  1318.             dopwd(theDir,256);                    /* get directory */
  1319.             sprintf(tempp,"remote --> %s/%s\015\012",theDir,newfile);
  1320.             ftpmess(tempp);
  1321.             netputevent(USERCLASS,FTPBEGIN,-2);
  1322.             
  1323.         case 31:
  1324. /*
  1325. * file has already been opened, take everything from the connection
  1326. * and place into the open file: ftpfh
  1327. */
  1328.             do {
  1329.             /* wait until xs is full before writing to disk */
  1330.                 if (len <= 2000) {
  1331.  
  1332.                     if (xp) {
  1333. #ifdef MACBINARY
  1334.                         if (0 > MBwrite(mbfp, xs, xp)) {
  1335.                             MBclose( mbfp);            /* Close on Disk Full Error */
  1336.                             ftpstate=22;
  1337.                             CRESP(fnum,27);                /* BYU 2.4.16 */
  1338.                             ftpmess(messs);
  1339.                             if( (a = netclose(ftpdata)) !=0 ) putln("error closing net ");
  1340.                             fcnt = -1;
  1341.                             mbfp=NULL;
  1342.  
  1343.                             putln("there is a problem");
  1344.                             break;
  1345.                         }
  1346. #else
  1347.                         if (0 > write(ftpfh,xs,xp)) { /* disk full err */
  1348.                             putln("\015\012we have a disk full error in asc\015\012");
  1349.  
  1350.                             CRESP(fnum,27);                /* BYU 2.4.16 */
  1351.                             netclose(ftpdata);
  1352.                             fcnt = -1;
  1353.  
  1354.                             break;
  1355.                         }
  1356. #endif
  1357.                         xp = 0;
  1358.                     }
  1359.                     len = BUFFERS;        /* expected or desired len to go */
  1360.                 }
  1361.  
  1362.                 if (ftptmode == FAMODE)
  1363.                     fcnt = Sfread(ftpdata,&xs[xp],len);
  1364.                 else
  1365.                     fcnt = netread(ftpdata,&xs[xp],len);
  1366.  
  1367.                 if (fcnt >= 0) {
  1368.                     len -= fcnt;
  1369.                     xp += fcnt;
  1370.                     filelen += fcnt;
  1371.                 }
  1372.  
  1373.                 if (fcnt < 0) {
  1374. #ifdef MACBINARY
  1375.                     if (0 > MBwrite( mbfp, xs, xp)) {
  1376.                         CRESP(fnum,27);            /* BYU 2.4.16 */
  1377.                         MBclose( mbfp);            /* Close file on error */
  1378.                         break;
  1379.                     }
  1380.                     MBclose( mbfp );
  1381. #else
  1382.                     if (0 > write(ftpfh,xs,xp)) { /* disk full check */
  1383.                         CRESP(fnum,27);                /* BYU 2.4.16 */
  1384.                         break;
  1385.                     }
  1386.                     close(ftpfh);
  1387. #endif
  1388.                     ftpfh = 0;
  1389.                     CRESP(fnum,5);                    /* BYU 2.4.16 */
  1390.                 }
  1391.  
  1392.             } while (fcnt > 0);
  1393.             break;
  1394.  
  1395.         case 20:
  1396.  
  1397.             if (code == CONFAIL)    /* something went wrong */
  1398.                 fcnt = -1;
  1399.             if (code != CONOPEN)    /* waiting for connection to open */
  1400.                 break;
  1401.             ftpstate = 21;
  1402. #ifdef MACBINARY
  1403.             filelen = MBsize( mbfp );
  1404. #else
  1405.             filelen = lseek(ftpfh,0L,2);        /* how long is file? */
  1406.             lseek(ftpfh,0L,0);                    /* back to beginning */
  1407. #endif
  1408.             towrite = 0;
  1409.             xp = 0;
  1410.             netputevent(USERCLASS,FTPBEGIN,-1);
  1411.  
  1412.         case 21:
  1413. /*
  1414. *  transfer file(s) to the other host via ftp request
  1415. *  file is already open = ftpfh
  1416. */
  1417.             netputuev(SCLASS,FTPACT,ftpdata);
  1418.         
  1419.             if (towrite <= xp) {
  1420.  
  1421.                 i = BUFFERS;
  1422. #ifdef MACBINARY
  1423.                 towrite = MBread( mbfp, xs, i);
  1424. #else
  1425.                 towrite = read(ftpfh,xs,i);
  1426. #endif
  1427.                 xp = 0;
  1428.             }
  1429.  
  1430.             if (towrite <= 0 || netest(ftpdata)) {        /* we are done */
  1431.                 ftpstate = 22;
  1432.                 break;
  1433.             }
  1434.  
  1435.             if (ftptmode == FAMODE)
  1436.                 i = Sfwrite(ftpdata,&xs[xp],towrite-xp);
  1437.             else
  1438.                 i = netwrite(ftpdata,&xs[xp],towrite-xp);
  1439.  
  1440.  
  1441. /*            printf(" %d %d %d \012",i,xp,towrite);
  1442.             n_row(); */
  1443.  
  1444.             if (i > 0) {
  1445.                 xp += i;
  1446.                 filelen -= i;
  1447.                 if (filelen < 0L)
  1448.                     filelen = 0L;
  1449.             }
  1450.  
  1451.             break;
  1452.  
  1453.         case 22:        /* wait for data to be accepted */
  1454.             netputuev(SCLASS,FTPACT,ftpdata);
  1455.  
  1456.             fcnt = netpush(ftpdata);        /* will go negative on err */
  1457.             if (!fcnt || netest(ftpdata))
  1458.                 fcnt = -1;
  1459.             if (fcnt < 0) {
  1460.                 CRESP(fnum,5);                /* BYU 2.4.16 */
  1461.             }
  1462.             break;
  1463.  
  1464.         case 0:
  1465.             break;
  1466.  
  1467.     }  /* end of switch */
  1468.  
  1469. /*
  1470. *  after reading from connection, if the connection is closed,
  1471. *  reset up shop.
  1472. */
  1473.     if (fcnt < 0) {
  1474. #ifdef MACBINARY
  1475.         if (mbfp) {
  1476.             MBclose( mbfp );
  1477.             mbfp = NULL;
  1478.  
  1479.  
  1480.  
  1481. /* */        
  1482.         }
  1483. #else
  1484.         if (ftpfh > 0) {
  1485.             close(ftpfh);
  1486.             ftpfh = 0;
  1487.         }
  1488. #endif
  1489.         ftpstate = 0;
  1490.         fcnt = 0;
  1491.         if (ftpdata >= 0) {
  1492.             netclose(ftpdata);
  1493.             netputevent(USERCLASS,FTPEND,-1);
  1494. /*            ftpdata = -1;                        /* BYU 2.4.16 */
  1495.             mainport[ftpdata] = -1;                /* BYU 2.4.16 */
  1496.             dataport[fnum] = -1;                /* BYU 2.4.16 */
  1497.         }
  1498.     }
  1499.  
  1500.     datastate[fnum] = ftpstate;            /* BYU 2.4.16 */
  1501.  
  1502. }
  1503.  
  1504. /***********************************************************************/
  1505. /* Sftpname and Sftpuser and Sftphost
  1506. *  record the name of the file being transferred, to use in the status
  1507. *  line updates
  1508. */
  1509.  
  1510. void Sftpname
  1511.   (
  1512.     char *s
  1513.   )
  1514.   {
  1515.     strcpy(s, newfile);
  1516.   }
  1517.  
  1518. void Sftpuser
  1519.   (
  1520.     char *user
  1521.   )
  1522.   {
  1523.     strcpy(user, myuser);            /* user name entered to log in */
  1524.   }
  1525.  
  1526. void Sftphost
  1527.   (
  1528.     char *host
  1529.   )
  1530.   {
  1531.     movebytes(host, hisuser, 4);        /* IP address of remote host */
  1532.   }
  1533.  
  1534. void Sftpstat
  1535.   (
  1536.     long *byt
  1537.   )
  1538.     {
  1539.     
  1540.     if (ftptmode != FAMODE && MacBinary)    /* MacBinary transfer */
  1541.         *byt = -1;
  1542.     else
  1543.         *byt = filelen;
  1544.  
  1545. }
  1546.  
  1547. #ifdef MACBINARY
  1548. void MBstat
  1549.   (
  1550.     char nlen,
  1551.     int godknows,
  1552.     int anotherlen
  1553.   )
  1554.   {
  1555. #pragma unused(nlen, godknows, anotherlen)
  1556.   }
  1557. #endif
  1558.